feat: Implement wallet initialization library#8838
Conversation
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
Hmm. I wonder if "instances" sounds a bit too vague. It's true they are instances of classes, but then so are lots of other things. For context, we discussed a unified term for controllers and services in this PR: https://github.com/MetaMask/decisions/pull/41#discussion_r1809429486. I had some ideas such as "messaging actor" (or just "actor"), but I think "messenger client" was the least worst option (and the one that Mark also agreed upon). "Messageable" was also a contender. Any of these options appeal to you? |
mcmire
left a comment
There was a problem hiding this comment.
Going in a good direction. Here are some thoughts and comments.
|
@metamaskbot publish-previews |
@mcmire I haven't spent much time thinking about this, when the prototyping started I don't believe we had adopted "messenger client" on the MetaMask clients yet. If that already is our decided preferred naming, I can make changes, but "messenger client" seems similarly vague and maybe even an overloaded term considering API clients, the MetaMask clients themselves (extension/mobile) etc. |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
Yeah, it's not not a perfect name for sure. I purposefully avoided using the term "messenger client" in my presentation for similar reasons. I don't think we have adopted the term widely, so we could come up with a different one and no one would bat an eye. I guess we could go with "instance" for now and maybe something else will pop out later. |
|
@FrederikBolding This looks pretty good to me so far. Let me know when this is out of draft. |
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
|
|
||
| export { defaultConfigurations }; | ||
|
|
||
| type ExtractInstance<Config> = |
There was a problem hiding this comment.
Would be helpful to have some docs for these types, since it may not be immediately obvious what some of these do.
| import type { InstanceSpecificOptions } from '../types'; | ||
| import type { DefaultActions, DefaultEvents, RootMessenger } from './defaults'; | ||
|
|
||
| export type InstanceState<Instance> = Instance extends { state: unknown } |
There was a problem hiding this comment.
I added documentation for some of them, any specific ones you think are still confusing? a2c4a8c
| const indices = phrase.split(' ').map((word) => wordlist.indexOf(word)); | ||
| const mnemonic = new Uint8Array(new Uint16Array(indices).buffer); |
There was a problem hiding this comment.
IIRC key-tree has a util function for this.
mcmire
left a comment
There was a problem hiding this comment.
Looks basically good, I just had one question about test coverage.
| import { initialize } from './initialization/initialization'; | ||
| import { WalletOptions } from './types'; | ||
|
|
||
| export class Wallet { |
There was a problem hiding this comment.
Nit: Would be good to add JSDoc that briefly describes the purpose of this class and provides an example. Same for the README. This can be done in a future PR, however.
|
@metamaskbot publish-previews |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8e35748. Configure here.
| }, | ||
| "dependencies": { | ||
| "@metamask/base-controller": "^9.1.0", | ||
| "@metamask/browser-passworder": "^6.0.0", |
There was a problem hiding this comment.
I guess we're using this package in a way that works across platforms? Curious if it might be worth it at some point to extract the more platform-agnostic functions to some other library. Otherwise it might be a bit confusing. We can think about that later perhaps.
There was a problem hiding this comment.
@metamask/browser-passworder works on most platforms except mobile, so it seemed fine to include. It's a good default option IMO.

Explanation
This PR implements a narrowly-scoped (as compared to the original feature branch) version of the wallet initialization library that only includes initializing the
KeyringController. This can eventually be used to demonstrate the integration of the library into the clients and serves as the base for future work.Overall it works in a similarly to the initialization pattern used in extension and mobile today, with some differences:
InitializationConfiguration. This object contains both a function to setup the messenger and the instance.InitializationConfiguration.messengeris expected to have access to actions/events necessary to initialize and operate the instance.There is no way to access the instances directly.The
Walletinstance provides access to the instances within using themessengerwhile also exposing a limited set of useful properties likestateandcontrollerMetadata.References
https://consensyssoftware.atlassian.net/browse/WPC-999
Checklist
Note
High Risk
Introduces vault encryption, keyring bootstrap, and SRP import paths—security-sensitive wallet/key material handling even though scope is limited to KeyringController.
Overview
Replaces the
@metamask/walletplaceholder with a wallet initialization library centered on aWalletclass that wires a root messenger, runs pluggableInitializationConfigurationentries, and exposes aggregatedstate,controllerMetadata, messenger access, and deprecatedgetInstance.The default stack currently boots
KeyringControlleronly, viainitialize()merging default configs with optional overrides by name, per-instance messengers, hydratedstate, andinstanceOptions(custom encryptor / keyring builders). Keyring setup adds a PBKDF2 (600k iterations)encryptorFactoryaroundbrowser-passworderand exportsimportSecretRecoveryPhrasefor SRP restore through messenger actions.Package surface: real runtime dependencies (
base-controller,keyring-controller,messenger, etc.), TS project references, changelog “initial release”, README dependency graph edges, and CODEOWNERS forkeyring-controllerinitialization. Tests cover wallet lifecycle, immutability guards, vault unlock/lock, encryptor behavior, and config overrides.Reviewed by Cursor Bugbot for commit 19bfd38. Bugbot is set up for automated code reviews on this repo. Configure here.